package fr.ants.view.panel;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import javax.swing.JComponent;

import fr.ants.model.Ant;
import fr.ants.model.Grid;
import fr.ants.model.Node;
import fr.ants.view.Renderer;
import fr.ants.view.Selection;
import fr.ants.view.renderer.AntRenderer;
import fr.ants.view.renderer.NestRenderer;
import fr.ants.view.renderer.NodeRenderer;
import fr.ants.view.renderer.ResourceRenderer;
import fr.ants.view.renderer.pixel.AntPixelRenderer;
import fr.ants.view.renderer.pixel.ColorMap;
import fr.ants.view.renderer.pixel.NestPixelRenderer;
import fr.ants.view.renderer.pokemon.NodePokemonRenderer;
import fr.ants.view.renderer.pokemon.ResourcePokemonRenderer;

/**
 * <p>
 * Canvas of the simulator, where are drawn all the elements.
 * </p>
 * 
 * @author Vianney DUPOY DE GUITARD
 */
public class Canvas extends JComponent {

	/** Serial UID. */
	private static final long serialVersionUID = 7893356016541856535L;

	/** Size, in pixels, of a node. */
	public static final int NODE_SIZE = 15;

	/** The grid to render. */
	private Grid grid;

	/** The color mapping used for ants and nests. */
	private ColorMap colorMap = new ColorMap();

	/** Renderer used for nodes. */
	private NodeRenderer nodeRenderer = new NodePokemonRenderer();

	/** Renderer used for nests. */
	private NestRenderer nestRenderer = new NestPixelRenderer(colorMap);

	/** Renderer used for ants. */
	private AntRenderer antRenderer = new AntPixelRenderer(colorMap);

	/** Renderer used for resources. */
	private ResourceRenderer resourceRenderer = new ResourcePokemonRenderer();

	/**
	 * to known the position of a component in the map. Null if none component
	 * selected.
	 */
	private Integer selectedX;
	/**
	 * to known the position of a component in the map. * Null if none component
	 * selected.
	 */
	private Integer selectedY;

	/**
	 * to known if we are in drawing mode
	 */
	private Selection selection = Selection.SELECTION;
	
	/**
	 * to known the renderer used
	 */
	private Renderer renderer = Renderer.POKEMON;


	/** Creates a new canvas. */
	public Canvas() {
		setOpaque(false);
	}

	/** {@inheritDoc} */
	@Override
	public void paint(Graphics g) {
		super.paint(g);
		if (grid != null) {
			Graphics2D g2d = (Graphics2D) g;
			g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);
			for (int x = 0; x < grid.getSizeX(); x++) {
				for (int y = 0; y < grid.getSizeY(); y++) {
					// Grab the nodes and elements on the node.
					Node node = grid.getNode(x, y);

					// Renders the node (ground).
					nodeRenderer.draw(x, y, g2d, node);

					if (node.getNest() != null) {
						// If there is a nest, the resources and ants are
						// underground.
						nestRenderer.draw(x, y, g2d, node.getNest());
					} else {
						// Otherwise, it renders the ants and resources (if
						// any).
						for (Ant ant : node.getAnts()) {
							antRenderer.draw(x, y, g2d, ant);
						}
						if (node.getResource() != null) {
							resourceRenderer
									.draw(x, y, g2d, node.getResource());
						}
					}
				}
			}
		}
	}

	/**
	 * Updates the canvas with a new grid.
	 */
	public void update(Grid pGrid) {
		grid = pGrid;
		setPreferredSize(new Dimension(getCanvasWidth(), getCanvasHeight()));
		firePropertyChange("grid", null, null);
		repaint();
	}

	/**
	 * @return the width of the canvas
	 */
	public int getCanvasWidth() {
		return grid.getSizeX() * NODE_SIZE;
	}

	/**
	 * 
	 * @return th height of the canvas
	 */
	public int getCanvasHeight() {
		return grid.getSizeY() * NODE_SIZE;
	}

	@Override
	public int getHeight() {
		if (grid != null) {
			return getCanvasHeight();
		}
		return super.getHeight();
	}

	@Override
	public int getWidth() {
		if (grid != null) {
			return getCanvasWidth();
		}
		return super.getWidth();
	}

	public Integer getSelectedGridX() {
		return selectedX;
	}

	public void setSelectedXY(Integer selectedX, Integer selectedY) {
		if (selectedX == null) {
			this.selectedX = null;
		} else {
			this.selectedX = selectedX / Canvas.NODE_SIZE;
		}
		if (selectedY == null) {
			this.selectedY = null;
		} else {
			this.selectedY = selectedY / Canvas.NODE_SIZE;
		}
		firePropertyChange("SelectedXY", null, null);
	}

	public Integer getSelectedGridY() {
		return selectedY;
	}

	public Grid getGrid() {
		return grid;
	}

	public Selection getSelection() {
		return selection;
	}

	public void setSelection(Selection selection) {
		this.selection = selection;
		firePropertyChange("Mode", null, null);
	}

	public Renderer getRenderer() {
		return renderer;
	}

	public void setRenderer(Renderer renderer) {
		this.renderer = renderer;
	}
	/**
	 * @return the nodeRenderer
	 */
	public NodeRenderer getNodeRenderer() {
		return nodeRenderer;
	}

	/**
	 * @param nodeRenderer the nodeRenderer to set
	 */
	public void setNodeRenderer(NodeRenderer nodeRenderer) {
		this.nodeRenderer = nodeRenderer;
	}
}